package org.springblade.modules.client;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import org.springblade.common.enums.IntegralType;
import org.springblade.common.enums.library.QuestionType;
import org.springblade.common.utils.CommonUtil;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.BeanUtil;
import org.springblade.core.tool.utils.CollectionUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.modules.classes.entity.TrainingPlanCourseEntity;
import org.springblade.modules.classes.service.ITrainingPlanService;
import org.springblade.modules.course.entity.CourseChapterSubEntity;
import org.springblade.modules.course.entity.CourseEntity;
import org.springblade.modules.course.entity.SubBankAnswerOptionEntity;
import org.springblade.modules.course.entity.SubVideoReadEntity;
import org.springblade.modules.course.service.ICourseChapterSubService;
import org.springblade.modules.course.service.ICourseService;
import org.springblade.modules.course.service.ISubBankAnswerOptionService;
import org.springblade.modules.course.service.ISubVideoReadService;
import org.springblade.modules.course.vo.CourseChapterSubVO;
import org.springblade.modules.course.vo.CourseVO;
import org.springblade.modules.course.wrapper.CourseWrapper;
import org.springblade.modules.library.bo.AutoExtractParamBO;
import org.springblade.modules.library.service.IQuestionBankService;
import org.springblade.modules.library.vo.QuestionBankVO;
import org.springblade.modules.library.vo.QuestionOptionVO;
import org.springblade.modules.log.entity.IntegralLogEntity;
import org.springblade.modules.log.service.IIntegralLogService;
import org.springblade.modules.log.vo.IntegralLogVO;
import org.springblade.modules.personal.service.IUserBaseService;
import org.springblade.modules.resource.enums.AttachType;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.*;


/**
 * 课程相关 客户端
 *
 * @author junxin
 * @since 2023-05-10
 */
@RestController
@AllArgsConstructor
@RequestMapping("blade-client/course")
@Api(value = "客户端课程相关接口", tags = "客户端课程相关接口")
public class ClientCourseController {

	private final ICourseService courseService;
	private final CommonUtil commonUtil;
	private final ICourseChapterSubService courseChapterSubService;
	private final IQuestionBankService questionBankService;
	private final ISubVideoReadService subVideoReadService;
	private final ISubBankAnswerOptionService subBankAnswerOptionService;
	private final ITrainingPlanService trainingPlanService;

	/**
	 * 查看课程详情
	 * 该课程下的所有章节、小节 及小节
	 */
	@GetMapping("/detail")
	@ApiOperationSupport(order = 1)
	@ApiOperation(value = "课程对应的章节、小节", notes = "传入courseId")
	public R<CourseVO> detail(Long courseId) {
		CourseVO info = courseService.getCourseInfo(courseId);
		return R.data(info);
	}

	/**
	 * 小节对应的学习视频
	 */
	@GetMapping("/sub-vedio")
	@ApiOperationSupport(order = 2)
	@ApiOperation(value = "小节对应的学习视频", notes = "subId")
	public R<CourseChapterSubVO> subVedio(Long subId) {
		return R.data(courseChapterSubService.queryBySubAndCategory(subId, AttachType.COURSE_VEDIO.getCategory()).get(0));
	}

	/**
	 * 小节对应的学习课件
	 */
	@GetMapping("/sub-courseware")
	@ApiOperationSupport(order = 3)
	@ApiOperation(value = "小节对应的学习课件", notes = "subId")
	public R<CourseChapterSubVO> subCourseware(Long subId) {
		return R.data(courseChapterSubService.queryCoursewareBySubAndCategory(subId, AttachType.COURSE_COURSEWARE.getCategory()));
	}

	/**
	 * 课程分页列表
	 */
	@GetMapping("/list")
	@ApiOperationSupport(order = 4)
	@ApiOperation(value = "课程分页列表", notes = "传入course")
	public R<IPage<CourseVO>> list(CourseVO course, Query query) {
		/**
		 * 添加保密等级 该用户能看到的保密等级
		 */
		course.setSecrecyLevel(commonUtil.getUserBaseEntity().getSecrecyLevel());
		IPage<CourseVO> pages = courseService.selectCoursePage(Condition.getPage(query), course);
		return R.data(pages);
	}

	@GetMapping("/myself-list")
	@ApiOperationSupport(order = 5)
	@ApiOperation(value = "我的课程分页列表", notes = "传入course")
	public R myCourselist(CourseVO course, Query query) {
		course.setUserId(AuthUtil.getUserId());
		IPage<CourseVO> pages = courseService.selectMyselfCoursePage(Condition.getPage(query), course);
		return R.data(pages);
	}


	/**
	 * 获取课后习题数据或学习视频弹出习题
	 */
	@GetMapping("/sub-bank-practice")
	@ApiOperationSupport(order = 6)
	@ApiOperation(value = "课后习题列表、学习视频弹出习题", notes = "type的值为1为弹出习题,type为2表示获取课后习题数据")
	public R subBankPractice(Long subId, Integer type) {
		List<QuestionBankVO> questionBankVOList = questionBankService.selectSubBankQuestionAndOption(subId, type);

		if (CollectionUtil.isEmpty(questionBankVOList) && type == 1) {//表示为视频卡点的试题
			AutoExtractParamBO bo = new AutoExtractParamBO();
			bo.setQuestionProperties("通用");
			bo.setExtractQuality(2);
			questionBankVOList = questionBankService.selectQuestionByParams(bo);
		}

		if (type == 2) {//如果是获取课后习题数据，则还要获取用户的作答数据
			Map<String, Object> resultMap = new HashMap<>();
			int isAnswer = 0;  //默认没有作答
			long count = subBankAnswerOptionService.count(Wrappers.<SubBankAnswerOptionEntity>query().lambda()
				.eq(SubBankAnswerOptionEntity::getUserId, AuthUtil.getUserId()).eq(SubBankAnswerOptionEntity::getSubId, subId));
			if (count > 0) {
				isAnswer = 1;
				questionBankVOList.forEach(vo -> {// 遍历题目
					List<QuestionOptionVO> answerOptionList = new ArrayList<>();
					vo.getOptionVOList().forEach(optionVo -> {//遍历题目的选项
//						List<SubBankAnswerOptionEntity> subBankAnswerOptionEntityList = subBankAnswerOptionService.queryByBankIdAndUserId(vo.getId(),AuthUtil.getUserId());
						QuestionOptionVO questionOptionVO = new QuestionOptionVO();
						BeanUtil.copy(optionVo, questionOptionVO);

						long answerCount = subBankAnswerOptionService.count(Wrappers.<SubBankAnswerOptionEntity>query().lambda()
							.eq(SubBankAnswerOptionEntity::getBankId, vo.getId())
							.eq(SubBankAnswerOptionEntity::getUserId, AuthUtil.getUserId())
							.eq(SubBankAnswerOptionEntity::getChecked, optionVo.getId())
							.eq(SubBankAnswerOptionEntity::getSubId, subId));
						if (answerCount > 0) {
							questionOptionVO.setChoice(1); //表示被选择了
						} else {
							questionOptionVO.setChoice(0);
							if (QuestionType.SHORT.getCode().intValue() == vo.getQuestionType()) {
								SubBankAnswerOptionEntity subBankAnswerOptionEntity = subBankAnswerOptionService.getOne(Wrappers.<SubBankAnswerOptionEntity>query().lambda()
									.eq(SubBankAnswerOptionEntity::getBankId, vo.getId())
									.eq(SubBankAnswerOptionEntity::getSubId, subId)
									.eq(SubBankAnswerOptionEntity::getUserId, AuthUtil.getUserId()));
								questionOptionVO.setOption(subBankAnswerOptionEntity.getAnswerContent());
							}
						}
						answerOptionList.add(questionOptionVO);
					});
					vo.setOptionVOList(new ArrayList<>());
					vo.setAnswerOptionList(answerOptionList);//题目选项及用户选择的选项
				});
			}
			//isAnswer=0 则前端拿optionVOList；isAnswer=1 则前端拿answerOptionList;
			resultMap.put("records", questionBankVOList);
			resultMap.put("isAnswer", isAnswer);
			return R.data(resultMap);
		}

		return R.data(questionBankVOList);
	}

	/**
	 * 用户提交课后习题的作答
	 */
	@PostMapping("/user-save-sub-bank-answer")
	@ApiOperationSupport(order = 7)
	@ApiOperation(value = "用户提交课后习题的作答", notes = "")
	public R userSaveSubBankAnswer(@RequestBody @Valid List<SubBankAnswerOptionEntity> list) {
		if (CollectionUtil.isEmpty(list)) R.success("操作成功");

		//如果该用户没有此课程的学习计划，则不记录
		Long userId = AuthUtil.getUserId();
		Long subId = list.get(0).getSubId();

		List<SubBankAnswerOptionEntity> dataList = new ArrayList<>();
		/**
		 * 统一都是用answerContent去接参数的，因此多选题需要做切割
		 */
		list.forEach(entity -> {
			if (QuestionType.MULTIPLE.getCode().equals(entity.getQuestionType()) && null != entity.getAnswerContent()) {
				List<Long> idList = Func.toLongList(entity.getAnswerContent());
				idList.forEach(optionId -> {
					SubBankAnswerOptionEntity data = new SubBankAnswerOptionEntity();
					BeanUtil.copyProperties(entity, data);
					data.setUserId(AuthUtil.getUserId());
					data.setChecked(optionId);
					dataList.add(data);
				});
			}
			if ((QuestionType.SINGLE.getCode().equals(entity.getQuestionType()) || QuestionType.JUDGE.getCode().equals(entity.getQuestionType()))
				&& null != entity.getAnswerContent()) {
				SubBankAnswerOptionEntity data = new SubBankAnswerOptionEntity();
				BeanUtil.copyProperties(entity, data);
				data.setUserId(userId);
				data.setChecked(Long.valueOf(data.getAnswerContent()));
				dataList.add(data);
			}
		});

		//检测积分派发情况
		CourseChapterSubEntity subEntity = courseChapterSubService.getById(subId);
		if (null != subEntity) checkCourseIntegral(userId, subEntity.getCourseId());

		return R.data(subBankAnswerOptionService.saveBatch(dataList));
	}


	/**
	 * 记录用户看完了该小节的学习视频
	 */
	@GetMapping("/user-video-completed")
	@ApiOperationSupport(order = 8)
	@ApiOperation(value = "记录用户看完视频", notes = "")
	@Transactional(rollbackFor = Exception.class)
	public R userVideoCompleted(Long subId) {
		Long userId = AuthUtil.getUserId();

		SubVideoReadEntity entity = new SubVideoReadEntity();
		entity.setUserId(userId);
		entity.setSubId(subId);
		long count = subVideoReadService.count(Wrappers.<SubVideoReadEntity>query().lambda()
			.eq(SubVideoReadEntity::getSubId, subId)
			.eq(SubVideoReadEntity::getUserId, userId));
		if (0 == count) {
			subVideoReadService.save(entity);

			//检测积分派发情况
			CourseChapterSubEntity subEntity = courseChapterSubService.getById(subId);
			if (null != subEntity) checkCourseIntegral(userId, subEntity.getCourseId());
		}

		return R.success("操作成功");
	}
	private final IIntegralLogService integralLogService;
	/**
	 * 检测该用户是否完成了所有的学习任务，如果是的话，派发积分
	 */
	@Transactional(rollbackFor = Exception.class)
	public void checkCourseIntegral(Long userId, Long courseId) {
		//该用户是否有对应的学习计划
		List<TrainingPlanCourseEntity> trainingPlanCourseEntityList = trainingPlanService.selectByUserIdAndCourseId(userId, courseId);
		if (CollectionUtil.isEmpty(trainingPlanCourseEntityList)) return;

		//如果需要考核测试 则不派发,会统一在完成课后作业之后派发
		if (trainingPlanCourseEntityList.get(0).getIsExam() == 1) return;
		//所有的学习任务是否已完成
		boolean flag = courseService.checkCourseComplete(courseId, userId);
		if (flag) {
			CourseEntity courseEntity = courseService.getById(courseId);
			IntegralLogVO vo = integralLogService.generalIntegralByCourse(courseEntity);
			vo.setUserId(userId);
			integralLogService.addIntegral(vo);
		}
	}


}
